package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.BusinessRuleInfoEntity;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.sys.help.PackageWhitelistHelp;
import com.xbongbong.paas.model.BusinessRuleInfoModel;
import com.xbongbong.paas.model.FineClueCompanyModel;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.SearchCustomerCompanyModel;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.service.EsignService;
import com.xbongbong.paas.service.PackageService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.MoneyUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.PackageConstant;
import com.xbongbong.pro.domain.entity.AiAssistantEntity;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.domain.entity.FineClueCompanyEntity;
import com.xbongbong.pro.domain.entity.SearchCustomerCompanyEntity;
import com.xbongbong.pro.enums.ContractCompareFeeStatusEnum;
import com.xbongbong.pro.enums.PackageStatusEnum;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.SoukeMealEnum;
import com.xbongbong.pro.enums.ValueAddedTypeEnum;
import com.xbongbong.pro.enums.ValueTypeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.FineClueComboEnum;
import com.xbongbong.pro.enums.menu.enums.SystemAppMenuEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.esign.pojo.vo.EsignContractMarginVO;
import com.xbongbong.pro.packageInfo.pojo.PackageLimitExceededPojo;
import com.xbongbong.pro.packageInfo.pojo.ValueAddedInfoPojo;
import com.xbongbong.pro.packageInfo.pojo.dto.BaseInfoDTO;
import com.xbongbong.pro.packageInfo.pojo.dto.PackageLimitExceededDTO;
import com.xbongbong.pro.packageInfo.pojo.dto.PackageValidDTO;
import com.xbongbong.pro.packageInfo.pojo.dto.SystemCapacityListDTO;
import com.xbongbong.pro.packageInfo.pojo.dto.ValueAddedInfosDTO;
import com.xbongbong.pro.packageInfo.pojo.vo.BaseInfoVO;
import com.xbongbong.pro.packageInfo.pojo.vo.BasePackageInfoVO;
import com.xbongbong.pro.packageInfo.pojo.vo.PackageLimitExceededVO;
import com.xbongbong.pro.packageInfo.pojo.vo.PackageLimitTipVO;
import com.xbongbong.pro.packageInfo.pojo.vo.PackageValidVO;
import com.xbongbong.pro.packageInfo.pojo.vo.SystemCapacityListVO;
import com.xbongbong.pro.packageInfo.pojo.vo.ValueAddedInfoVO;
import com.xbongbong.pro.sms.model.SmsConfigModel;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.model.ChartCustomModel;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SmsConfigEntity;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.ContractComparePackageEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.FineCluePackageEnum;
import com.xbongbong.saas.model.AiAssistantModel;
import com.xbongbong.saas.service.toolbox.help.UpdatePackageRedisService;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.domain.entity.FeeEntity;
import com.xbongbong.sys.domain.entity.FeeLogEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.help.SysEnvHelp;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.FeeLogModel;
import com.xbongbong.sys.model.FeeModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.util.ContractCompareUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 套餐
 * 创建时间 2019/5/13 11:04 AM
 * 修改时间 2019/5/13 11:04 AM
 * @author chy
 * @since v1.0
 * @version v1.0
 */
@Service("packageService")
public class PackageServiceImpl implements PackageService {
    private static final Logger LOG = LoggerFactory.getLogger(PackageServiceImpl.class);

    @Resource
    private CompanyModel companyModel;
    @Resource
    private UserModel userModel;
    @Resource
    private SmsConfigModel smsConfigModel;
    @Resource
    private SearchCustomerCompanyModel searchCustomerCompanyModel;
    @Resource
    @Lazy
    private UpdatePackageRedisService updatePackageRedisService;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private FeeModel feeModel;
    @Resource
    private FeeLogModel feeLogModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private AiAssistantModel aiAssistantModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private ChartCustomModel chartCustomModel;
    @Resource
    private BusinessRuleInfoModel businessRuleInfoModel;
    @Resource
    private EsignService esignService;
    @Resource
    private PackageWhitelistHelp packageWhitelistHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private FineClueCompanyModel fineClueCompanyModel;
    @Resource
    private SysEnvHelp sysEnvHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private ContractCompareUtil contractCompareUtil;

    @Override
    public BaseInfoVO getBasePackageInfo(BaseInfoDTO baseInfoDTO) throws XbbException {

        BaseInfoVO baseInfoVO = new BaseInfoVO();

        String corpid = baseInfoDTO.getCorpid();
        CompanyEntity company = companyModel.getByKey(corpid);

        if (company == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100011);
        }

        BasePackageInfoVO basePackageInfoVO = getBasePackageInfoFromRedis(corpid);
        if (basePackageInfoVO != null) {
//            String feeName = StringUtil.isEmpty(basePackageInfoVO.getFeeName()) ? "" : basePackageInfoVO.getFeeName();
            baseInfoVO.setCorpid(corpid);
            baseInfoVO.setCorpName(company.getCorpName());

            Integer feeType = basePackageInfoVO.getFeeType();

            baseInfoVO.setFeeName(PackageTypeEnum.getNameByType(feeType));
            Long feeStartTime = basePackageInfoVO.getFeeStartTime() == null ? DateTimeUtil.getInt() : basePackageInfoVO.getFeeStartTime();
            String startTime = DateTimeUtil.getStringEpochSecond(feeStartTime, "yyyy/MM/dd");
            baseInfoVO.setStartTime(startTime);

            Long feeEndTime = basePackageInfoVO.getFeeEndTime() == null ? DateTimeUtil.getInt() : basePackageInfoVO.getFeeEndTime();
            String endTime = DateTimeUtil.getStringEpochSecond(feeEndTime, "yyyy/MM/dd");
            baseInfoVO.setEndTime(endTime);

            Long today = DateTimeUtil.getTodayInt();

            Long leftDay = (feeEndTime - today) / TimeConstant.SECONDS_PER_DAY + 1;

            baseInfoVO.setLeftDay(leftDay.intValue());
            baseInfoVO.setIsFree(basePackageInfoVO.getIsFree());
        }

        String userId = baseInfoDTO.getUserId();
        UserEntity user = userModel.getByKey(userId, corpid);

        if (user == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, MessageConstant.USER_NOT_EXIST);
        }

        String avatar = user.getAvatar();
        String userName = user.getName();
        baseInfoVO.setUserName(userName);
        baseInfoVO.setAvatar(avatar);

        baseInfoVO.setSupportHotline(StringConstant.SUPPORT_HOTLINE);
        return baseInfoVO;
    }

    @Override
    public ValueAddedInfoVO getValueAddedInfos(ValueAddedInfosDTO valueAddedInfoDTO) throws XbbException {
        ValueAddedInfoVO valueAddedInfoVO = new ValueAddedInfoVO();
        String corpid = valueAddedInfoDTO.getCorpid();
        List<ValueAddedInfoPojo> systemCapacityList = getSystemCapacityList(corpid);
        valueAddedInfoVO.setSystemCapacityList(systemCapacityList);
        List<ValueAddedInfoPojo> advancedFunctionList = getAdvancedFunctionList(corpid);
        valueAddedInfoVO.setAdvancedFunctionList(advancedFunctionList);
        List<ValueAddedInfoPojo> thirdPartyList = getThirdPartyList(corpid);
        valueAddedInfoVO.setThirdPartyList(thirdPartyList);

        return valueAddedInfoVO;
    }

    @Override
    public SystemCapacityListVO getSystemCapacityList(SystemCapacityListDTO systemCapacityListDTO) throws XbbException {
        SystemCapacityListVO systemCapacityListVO = new SystemCapacityListVO();
        String corpid = systemCapacityListDTO.getCorpid();
        String userId = systemCapacityListDTO.getUserId();

        BasePackageInfoVO basePackageInfoVO = getBasePackageInfoFromRedis(corpid);

        Long feeEndTime = basePackageInfoVO.getFeeEndTime() == null ? 0L : basePackageInfoVO.getFeeEndTime();

        Integer feeType = basePackageInfoVO.getFeeType();

        systemCapacityListVO.setFeeName(PackageTypeEnum.getNameByType(feeType));
        Boolean isAdminOrBoss = systemCapacityListDTO.getLoginUser().isAdminOrBoss();
        systemCapacityListVO.setIsAdminOrBoss(isAdminOrBoss);
        if (isAdminOrBoss){
            Long today = DateTimeUtil.getTodayInt();
            Long leftDay = (feeEndTime - today) / TimeConstant.SECONDS_PER_DAY + 1;
            systemCapacityListVO.setLeftDay(leftDay.intValue());
        }

        systemCapacityListVO.setSupportHotline(StringConstant.SUPPORT_HOTLINE);
        systemCapacityListVO.setSupportHotlineCall(StringConstant.SUPPORT_HOTLINE_NO_LINE);
        UserEntity user = userModel.getByKey(userId, corpid);

        if (user == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, I18nStringConstant.LOGIN_USER_DOES_NOT_EXIST);
        }

        String avatar = user.getAvatar();
        String userName = user.getName();
        systemCapacityListVO.setUserName(userName);
        systemCapacityListVO.setAvatar(avatar);

        List<ValueAddedInfoPojo> systemCapacityList = getSystemCapacityList(corpid);
        systemCapacityListVO.setSystemCapacityList(systemCapacityList);

        // 国际化白名单
        CompanyConfigEntity entity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.I18N_WHITE.getAlias(), PaasConstant.DEFAULT_DATA_CORPID);
        String value = CompanyConfigEnum.I18N_WHITE.getValue();
        if (Objects.nonNull(entity)) {
            value = entity.getConfigValue();
        }
        List<String> whiteList = JsonHelperUtil.parseArray(value, String.class);
        boolean flag = CollectionsUtil.isNotEmpty(whiteList) && whiteList.contains(corpid);
        systemCapacityListVO.setMultiLang(flag);
        systemCapacityListVO.setIsGray(sysEnvHelp.isGrayEnvironment());
        return systemCapacityListVO;
    }

    @Override
    public BasePackageInfoVO getBasePackageInfoFromRedis(String corpid) throws XbbException {
        return packageHelp.getBasePackageInfoFromRedis(corpid);
    }

    /**
     * 获取版本
     * @param corpid
     * @return
     * @throws XbbException
     */
    @Override
    public Integer getFeeType(String corpid) throws XbbException {
        return packageHelp.getFeeType(corpid);
    }

    @Override
    public PackageValidVO packageValidate(PackageValidDTO packageValidDTO) throws XbbException {
        PackageValidVO packageValidVO = new PackageValidVO();
        try {
            Integer type = packageValidDTO.getType();
            ValueAddedTypeEnum valueAddedTypeEnum = ValueAddedTypeEnum.getByType(type);
            Integer num = updatePackageRedisService.getUnusedNumPackageLimit(packageValidDTO.getCorpid(), valueAddedTypeEnum);
            packageValidVO.setPackageLimit(0);

            switch (valueAddedTypeEnum) {
                case CUSTOM_FORM_NUM:
                    if (Objects.equals(SaasMarkEnum.PAAS.getCode(), packageValidDTO.getSaasMark())) {
                        if (Objects.isNull(packageValidDTO.getMenuId())) {
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_ID_NOT_EXIST);
                        }
                        PaasFormEntity paasFormEntity = paasFormModel.getByMenuId(packageValidDTO.getMenuId(), packageValidDTO.getCorpid());
                        if (Objects.isNull(paasFormEntity)) {
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                        }
                        PaasAppEntity paasAppEntity = paasAppModel.getByKey(paasFormEntity.getAppId(), packageValidDTO.getCorpid());
                        if (Objects.isNull(paasAppEntity)) {
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
                        }
                        if (num <=0 && Objects.equals(SaasMarkEnum.PAAS.getCode(), paasAppEntity.getSaasMark())) {
                            valueAddedTypeEnum = ValueAddedTypeEnum.CUSTOM_APPLICATION_NUM;
                            num = updatePackageRedisService.getUnusedNumPackageLimit(packageValidDTO.getCorpid(), ValueAddedTypeEnum.CUSTOM_APPLICATION_NUM);
                        }
                        if (num > 0) {
                            if (Objects.equals(ValueAddedTypeEnum.CUSTOM_FORM_NUM.getType(), valueAddedTypeEnum.getType())) {
                                packageValidVO.setMessage(String.format(I18nMessageUtil.getMessage(PackageConstant.CUSTOM_FORM_SIZE_MESSAGE), num));
                            } else {
                                packageValidVO.setMessage(String.format(I18nMessageUtil.getMessage(PackageConstant.APPLICATION_PACKAGE_LIMIT_MESSAGE)));
                            }
                            if (packageValidDTO.getLoginUser().isAdmin()) {
                                packageValidVO.setDelete(1);
                                packageValidVO.setUpgrade(1);
                            }
                            packageValidVO.setPackageLimit(1);
                            packageValidVO.setName(paasFormEntity.getName());
                        }
                    }
                    break;
                case AI_ASSISTANT:
                    if (num > 0) {
                        packageValidVO.setPackageLimit(1);
                        packageValidVO.setMessage(String.format(I18nMessageUtil.getMessage(PackageConstant.AI_ASSISTANT_SIZE_MESSAGE), num));
                        if (packageValidDTO.getLoginUser().isAdmin()) {
                            packageValidVO.setUpgrade(1);
                        }
                    }

                    break;
                default:
                    break;
            }

        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PackageServiceImpl.packageLimitForm  出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return packageValidVO;
    }

    @Override
    public PackageLimitExceededVO limitExceeded(PackageLimitExceededDTO packageLimitExceededDTO) throws XbbException {
        PackageLimitExceededVO packageLimitExceededVO = new PackageLimitExceededVO();
        try {
            List<PackageLimitExceededPojo> packageLimitList = new ArrayList<>();
            String corpid = packageLimitExceededDTO.getCorpid();
            Integer feeType = getFeeType(corpid);
            if (Objects.equals(PackageTypeEnum.ULTIMATE.getType(), feeType)) {
                packageLimitExceededVO.setPackageLimitList(new ArrayList<>());
                packageLimitExceededVO.setPageHelper(new PageHelper(packageLimitExceededDTO.getPage(), packageLimitExceededDTO.getPageSize()));
                return packageLimitExceededVO;
            }
            Integer type = packageLimitExceededDTO.getType();
            ValueAddedTypeEnum valueAddedTypeEnum = ValueAddedTypeEnum.getByType(type);
            if (valueAddedTypeEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            Set<Long> formIdIn = new HashSet<>();
            boolean isAdmin = packageLimitExceededDTO.getLoginUser().isAdmin();
            Set<String> permission = packageLimitExceededDTO.getLoginUser().getPermSet();
            Integer num = updatePackageRedisService.getUnusedNumPackageLimit(corpid, valueAddedTypeEnum);
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.CORPID, corpid);
            PageHelper pageHelper = new PageHelper(packageLimitExceededDTO.getPage(), packageLimitExceededDTO.getPageSize());
            String key = corpid + "_"+ type;
            paasRedisHelper.removeValue(RedisPrefixConstant.VALUE_ADDED, key);
            switch (valueAddedTypeEnum) {
                case CUSTOM_APPLICATION_NUM:
                    // 自定义应用
                    param.put("saasMark", SaasMarkEnum.PAAS.getCode());
                    boolean delete = isAdmin && permission.contains(ProPermissionAliasEnum.APPLICATION_SET_VIEW.getAlias());
                    List<PaasAppEntity> appList = (List<PaasAppEntity>) PageHelperUtil.getEntityListNoTotal(param, pageHelper, paasAppModel);
                    if (CollectionsUtil.isNotEmpty(appList)) {
                        appList.forEach(item->{
                            String name = item.getName();
                            String message = I18nMessageUtil.getMessage(String.format(I18nMessageUtil.getMessage(PackageConstant.FEATURE_SIZE_MESSAGE), num));
                            message = "【"+name+"】" + message;
                            PackageLimitExceededPojo packageLimitExceededPojo = new PackageLimitExceededPojo(message, delete, type, item.getId(), null, null, null, null);
                            packageLimitList.add(packageLimitExceededPojo);
                        });
                    }
                    break;
                case CUSTOM_FORM_NUM:
                    // 自定义表单
                    param.put(StringConstant.SAAS_MARK, SaasMarkEnum.PAAS.getCode());
                    List<PaasFormEntity> formList = (List<PaasFormEntity>) PageHelperUtil.getEntityListNoTotal(param, pageHelper, paasFormModel);
                    delete = isAdmin && permission.contains(ProPermissionAliasEnum.FORM_SET_VIEW.getAlias());
                    if (CollectionsUtil.isNotEmpty(formList)) {
                        formList.forEach(item->{
                            String name = item.getName();
                            String message = I18nMessageUtil.getMessage(String.format(I18nMessageUtil.getMessage(PackageConstant.FEATURE_SIZE_MESSAGE), num));
                            message = "【"+name+"】" + message;
                            PackageLimitExceededPojo packageLimitExceededPojo = new PackageLimitExceededPojo(message, delete, type, item.getAppId(), item.getId(), item.getMenuId(), item.getSaasMark(), item.getBusinessType());
                            packageLimitList.add(packageLimitExceededPojo);
                        });
                    }
                    break;
                case CUSTOM_CHART_NUM:
                    // 自定义图表
                    param.put("chartTypeIn", ChartTypeEnum.getCustomChartType());
                    List<ChartEntity> chartList = (List<ChartEntity>) PageHelperUtil.getEntityListNoTotal(param, pageHelper, chartCustomModel);
                    if (CollectionsUtil.isNotEmpty(chartList)) {
                        delete = isAdmin && permission.contains(ProPermissionAliasEnum.CHART_CENTER.getAlias());
                        chartList.forEach(item->{
                            String name = item.getName();
                            String message = I18nMessageUtil.getMessage(String.format(I18nMessageUtil.getMessage(PackageConstant.FEATURE_SIZE_MESSAGE), num));
                            message = "【"+name+"】" + message;
                            PackageLimitExceededPojo packageLimitExceededPojo = new PackageLimitExceededPojo(message, delete, type, item.getId());
                            packageLimitList.add(packageLimitExceededPojo);
                        });
                    }
                    break;
                case AI_ASSISTANT:
                    // 智能助手
                    param.put("enable", 1);
                    pageHelper = new PageHelper(packageLimitExceededDTO.getPage(), packageLimitExceededDTO.getPageSize());
                    List<AiAssistantEntity> aiAssistantList = (List<AiAssistantEntity>) PageHelperUtil.getEntityListNoTotal(param, pageHelper, aiAssistantModel);
                    if (CollectionsUtil.isNotEmpty(aiAssistantList)) {
                        Map<Long, String> aiAssistantNameMap = new HashMap<>(aiAssistantList.size());
                        aiAssistantList.forEach(item->{
                            formIdIn.add(item.getFormId());
                            if (aiAssistantNameMap.containsKey(item.getFormId())) {
                                String name = aiAssistantNameMap.get(item.getFormId());
                                name = name + "「"+item.getName()+"」";
                                aiAssistantNameMap.put(item.getFormId(), name);
                            } else {
                                String name = "「"+item.getName()+"」" ;
                                aiAssistantNameMap.put(item.getFormId(), name);
                            }
                        });
                        param.clear();
                        param.put("idIn", formIdIn);
                        param.put(StringConstant.CORPID, corpid);
                        List<PaasFormEntity> formIdList = paasFormModel.findEntity(param);
                        if (Objects.isNull(formIdList)) {
                            formIdList = new ArrayList<>();
                        }
                        delete = isAdmin && permission.contains(ProPermissionAliasEnum.AI_ASSISTANT.getAlias());
                        formIdList.forEach(item->{
                            if (aiAssistantNameMap.containsKey(item.getId())) {
                              String message =  "【" + item.getName() + "】" + aiAssistantNameMap.get(item.getId()) + I18nMessageUtil.getMessage(PackageConstant.PACKAGE_LIMIT_MESSAGE);
                                PackageLimitExceededPojo packageLimitExceededPojo = new PackageLimitExceededPojo(message, delete, type, item.getAppId(), item.getId(), null, null, null);
                                packageLimitList.add(packageLimitExceededPojo);
                            }
                        });
                    }
                    break;
                case BUSINESS_RULES:
                    // 业务规则
                    List<BusinessRuleInfoEntity> businessRuleInfoList = (List<BusinessRuleInfoEntity>) PageHelperUtil.getEntityListNoTotal(param, pageHelper, businessRuleInfoModel);
                    if (CollectionsUtil.isNotEmpty(businessRuleInfoList)) {
                        Map<Long, String> nameMap = new HashMap<>(businessRuleInfoList.size());
                        businessRuleInfoList.forEach(item->{

                            if (Objects.nonNull(item.getFormId())) {
                                formIdIn.add(item.getFormId());
                                if (nameMap.containsKey(item.getFormId())) {
                                    String name = nameMap.get(item.getFormId());
                                    if (StringUtil.isNotEmpty(item.getActiveName())) {
                                        name = name + "「"+item.getActiveName()+"」";
                                    }
                                    if (StringUtil.isNotEmpty(item.getInactiveName())) {
                                        name = name + "「"+item.getInactiveName()+"」";
                                    }

                                    nameMap.put(item.getFormId(), name);
                                } else {
                                    String name = "";
                                    if (StringUtil.isNotEmpty(item.getActiveName())) {
                                        name = name + "「"+item.getActiveName()+"」";
                                    }
                                    if (StringUtil.isNotEmpty(item.getInactiveName())) {
                                        name = name + "「"+item.getInactiveName()+"」";
                                    }

                                    nameMap.put(item.getFormId(), name);
                                }
                            }
                        });
                        param.clear();
                        param.put("idIn", formIdIn);
                        param.put(StringConstant.CORPID, corpid);
                        List<PaasFormEntity> formIdList = paasFormModel.findEntity(param);
                        if (Objects.isNull(formIdList)) {
                            formIdList = new ArrayList<>();
                        }
                        delete = isAdmin && permission.contains(ProPermissionAliasEnum.FORM_SET_VIEW.getAlias());
                        formIdList.forEach(item->{
                            if (nameMap.containsKey(item.getId())) {
                                String message =  "【" + item.getName() + "】" + nameMap.get(item.getId()) + I18nMessageUtil.getMessage(PackageConstant.PACKAGE_LIMIT_MESSAGE);
                                PackageLimitExceededPojo packageLimitExceededPojo = new PackageLimitExceededPojo(message, delete, type, item.getAppId(), item.getId(), item.getMenuId(), item.getSaasMark(), item.getBusinessType());
                                packageLimitList.add(packageLimitExceededPojo);
                            }
                        });
                    }
                    break;
                default:
                    break;
            }
            packageLimitExceededVO.setPackageLimitList(packageLimitList);
            packageLimitExceededVO.setPageHelper(pageHelper);
        } catch (XbbException e) {
            throw e;
        }catch (Exception e) {
            LOG.error("PackageServiceImpl.limitExceeded  出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return packageLimitExceededVO;
    }


    @Override
    public PackageLimitTipVO limitTip(BaseDTO baseDTO) throws XbbException {
        PackageLimitTipVO packageLimitTipVO = new PackageLimitTipVO();
        try {
            packageLimitTipVO.setPackageLimit(0);
            String corpid = baseDTO.getCorpid();
            BasePackageInfoVO basePackageInfoVO = getBasePackageInfoFromRedis(corpid);
            // 如果套餐起始时间大于套餐降级上线时间，那么该公司需要从套餐白名单中剔除
            packageWhitelistHelp.setPackageWhitelist(corpid, basePackageInfoVO.getFeeStartTime());
            Set<String> corpidSet = packageWhitelistHelp.getPackageWhitelist(corpid);
            if (corpidSet.contains(corpid)) {
                return packageLimitTipVO;
            }
            Integer feeType = getFeeType(corpid);
            if (Objects.equals(PackageTypeEnum.ULTIMATE.getType(), feeType)) {
                return packageLimitTipVO;
            }
            List<Map<String, Object>> packageLimitList = new ArrayList<>();
            for (ValueAddedTypeEnum valueAddedTypeEnum: ValueAddedTypeEnum.getValueAddedType()) {
                Integer num = updatePackageRedisService.getUnusedNumPackageLimit(corpid, valueAddedTypeEnum);
                if (num > 0) {
                    Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    map.put("name", valueAddedTypeEnum.getName());
                    map.put("type", valueAddedTypeEnum.getType());
                    if (Objects.equals(PackageTypeEnum.STANDARD.getType(), feeType)
                            && Objects.equals(ValueAddedTypeEnum.BUSINESS_RULES.getType(), valueAddedTypeEnum.getType())) {
                        continue;
                    }
                    packageLimitList.add(map);
                }
            }
            Integer delete = baseDTO.getLoginUser().isAdmin() ? 1 : 0;
            Integer upgrade  = baseDTO.getLoginUser().isAdmin() ? 1 : 0;
            packageLimitTipVO.setDelete(delete);
            packageLimitTipVO.setUpgrade(upgrade);
            if (CollectionsUtil.isNotEmpty(packageLimitList)) {
                packageLimitTipVO.setPackageLimit(1);
                packageLimitTipVO.setMessage(I18nMessageUtil.getMessage(PackageConstant.VERSION_MESSAGE));
                packageLimitTipVO.setPackageLimitList(packageLimitList);
            }
        } catch (Exception e) {
            LOG.error("limitTip出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return packageLimitTipVO;
    }

    /**
     * 应用数量
     * @param corpid
     * @return
     * @throws XbbException
     */
    private List<ValueAddedInfoPojo> getAdvancedFunctionList(String corpid) throws XbbException {
        List<ValueAddedInfoPojo> advancedFunctionList = new ArrayList<>();

        ValueAddedInfoPojo customApplicationNum = getSimpleInfo(corpid, ValueAddedTypeEnum.CUSTOM_APPLICATION_NUM,
                ValueTypeEnum.CUSTOM_APPLICATION_NUM);
        ValueAddedInfoPojo customFormNum = getSimpleInfo(corpid, ValueAddedTypeEnum.CUSTOM_FORM_NUM,
                ValueTypeEnum.CUSTOM_FORM_NUM);
        ValueAddedInfoPojo customProcessNum = getCustomProcessInfo(corpid);
        ValueAddedInfoPojo customChartNum = getCustomChartNumInfo(corpid);
        ValueAddedInfoPojo customPrint = getCustomPrintInfo(corpid);
        ValueAddedInfoPojo importAndExport = getImportAndExportInfo(corpid);
        ValueAddedInfoPojo callCenter = getCallCenterInfo(corpid);
        ValueAddedInfoPojo sfa = getSfaNumInfo(corpid);
        ValueAddedInfoPojo api = getApiInfo(corpid);
        ValueAddedInfoPojo distributor = getDistributorInfo(corpid);
        ValueAddedInfoPojo businessRules = getBusinessRulesInfo(corpid);
        ValueAddedInfoPojo workOrderV2 = getWorkOrderV2(corpid);

        advancedFunctionList.add(customApplicationNum);
        advancedFunctionList.add(customFormNum);
        advancedFunctionList.add(customProcessNum);
        advancedFunctionList.add(customChartNum);
        advancedFunctionList.add(customPrint);
        advancedFunctionList.add(importAndExport);
        advancedFunctionList.add(callCenter);
        advancedFunctionList.add(sfa);
        advancedFunctionList.add(api);
        advancedFunctionList.add(workOrderV2);
//        fix:47829 【业务规则】工作流公司不应该展示业务规则套餐
        if (isPackageShowBusinessRule(corpid)) {
            advancedFunctionList.add(businessRules);
        }
        advancedFunctionList.add(distributor);
        return advancedFunctionList;
    }

    /**
     * 第三方应用余量
     * @param corpid
     * @return
     * @throws XbbException
     */
    private List<ValueAddedInfoPojo> getThirdPartyList(String corpid) throws XbbException {
        List<ValueAddedInfoPojo> thirdPartyList = new ArrayList<>();

        ValueAddedInfoPojo souke = getSoukeNumInfo(corpid);
        if(Objects.nonNull(souke)){
            // 开通搜客应用
            thirdPartyList.add(souke);
        }
        // 工商查询
        ValueAddedInfoPojo businessSearch = getBusinessSearchNumInfo(corpid);
        if(Objects.nonNull(businessSearch)){
            // 开通搜客应用
            thirdPartyList.add(businessSearch);
        }
        // 合同比对
        ValueAddedInfoPojo contracrCompareNumInfo = getContracrCompareNumInfo(corpid);
        if (Objects.nonNull(contracrCompareNumInfo)){
            thirdPartyList.add(contracrCompareNumInfo);
        }

        ValueAddedInfoPojo esign = null;
        try {
            esign = getEsignNumInfo(corpid);
        } catch (XbbException e) {
            //e签宝信息获取失败
        }

        if(Objects.nonNull(esign)){
            // 开通e签宝应用
            thirdPartyList.add(esign);
        }
        return thirdPartyList;
    }

    private ValueAddedInfoPojo getCustomProcessInfo(String corpid) {
        Integer totalValue = 1;
        Integer usedValue = 1;
        String userValueStr = "";
        if (Objects.equals(usedValue, 1)) {
            userValueStr = OperateTypeEnum.ENABLE.getName();
        } else {
            userValueStr = OperateTypeEnum.CLOSE.getName();
        }
        Float percentage = 100F;
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.UNLIMITED_NUMBER_PROCESSES);
        String warningMemo = "";
        ValueAddedInfoPojo customProcess = new ValueAddedInfoPojo(ValueTypeEnum.CUSTOM_PROCESS_NUM,
                totalValue, usedValue, userValueStr, percentage, memo, warningMemo);
        return customProcess;
    }

    /**
     * 智能报表
     * @param corpid
     * @return
     * @throws XbbException
     */
    private ValueAddedInfoPojo getSfaNumInfo(String corpid) throws XbbException {

        //{"totalValue":2, "usedValue":1, "status":1}
        JSONObject sfaNumData = getValueAddInfo(corpid, ValueAddedTypeEnum.AI_ASSISTANT, null, null);
        Integer totalValue = sfaNumData.getInteger("totalValue");
        Integer usedValue = sfaNumData.getInteger("usedValue");
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
        String usedValueStr = "";
        String memo = totalValue + I18nMessageUtil.getMessage(CommonConstant.EACH);
        String warningMemo = "";

        ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.SFA_NUM,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return formData;
    }

    /**
     * 搜客
     * @param corpid
     * @return ValueAddedInfoPojo
     * @author 石安
     * @date 2019-08-15
     */
    private ValueAddedInfoPojo getSoukeNumInfo(String corpid){
        // 精线索提供的搜客
        FineClueCompanyEntity fineClueCompanyEntity = fineClueCompanyModel.getByCorpid(corpid, FineClueComboEnum.FINE_CLUE.getCode());
        if (fineClueCompanyEntity != null && fineClueCompanyEntity.getExtraExpiry() > DateTimeUtil.getInt()) {
            // 是否为试用
            boolean trialFlag = fineClueCompanyEntity.getExtraExpiry() - fineClueCompanyEntity.getAddTime() < 4 * RedisTimeConstant.LONG_DURATION;
            Integer totalValue = fineClueCompanyEntity.getUseCount();
            Integer usedValue = 1;
            Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
            FineCluePackageEnum fineCluePackageEnum = FineCluePackageEnum.getFineClueByNumType(fineClueCompanyEntity.getNumType());
            String memo = trialFlag ? FineCluePackageEnum.FINE_CLUE_TRIAL.getMemo() :
                    Objects.nonNull(fineCluePackageEnum) ? I18nMessageUtil.getMessage(fineCluePackageEnum.getMemo()) : "";

            return new ValueAddedInfoPojo(ValueTypeEnum.SEARCH_CUSTOMER,
                    totalValue, usedValue, "", percentage, memo, "");
        }
        SearchCustomerCompanyEntity soukeEntity = searchCustomerCompanyModel.getByCorpid(corpid, SoukeMealEnum.SOUKE.getType());
        if(soukeEntity != null && soukeEntity.getExtraExpiry() > DateUtil.getInt()){
            Integer totalValue = soukeEntity.getUseCount();
            Integer usedValue = 1;
            Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
            String memo = totalValue + I18nMessageUtil.getMessage(CommonConstant.EACH);

            return new ValueAddedInfoPojo(ValueTypeEnum.SEARCH_CUSTOMER,
                    totalValue, usedValue, "", percentage, memo, "");
        }
        return null;
    }

    private ValueAddedInfoPojo getContracrCompareNumInfo(String corpid){

        //
        Integer compareStatus = contractCompareUtil.getContractCompareStatus(corpid);
        if (Objects.equals(compareStatus, ContractCompareFeeStatusEnum.TRIAL.getType()) || Objects.equals(compareStatus, ContractCompareFeeStatusEnum.OVERDUE.getType())){
            return null;
        }
        Float percentage = 0f;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("feeType",ValueAddedTypeEnum.CONTRACT_COMPARE.getType());
        param.put("orderByStrDesc","start_time");
        param.put("start",0);
        param.put("pageNum",1);
        List<FeeLogEntity> feeLogEntitys = feeLogModel.findEntitys(param);
        if (CollectionsUtil.isEmpty(feeLogEntitys)){
            return null;
        }
        FeeLogEntity feeLogEntity = feeLogEntitys.get(0);
        ContractComparePackageEnum comparePackageEnum = ContractComparePackageEnum.getFeeTypeByFeeName(feeLogEntity.getFeeName());
        String memo = comparePackageEnum.getMemo();
        return new ValueAddedInfoPojo(ValueTypeEnum.CONTRACTCOMPARE, 0, 0,"", percentage, memo, "");
    }

    /***
     * 工商查询
     *
     * @param corpid
     * @throws
     * @return ValueAddedInfoPojo
     * @author hongxiao
     * @date 2022-01-08 18:02
     * @since
     * @version
     */
    private ValueAddedInfoPojo getBusinessSearchNumInfo(String corpid){
        // 精线索提供的工商查询
        FineClueCompanyEntity fineClueCompanyEntity = fineClueCompanyModel.getByCorpid(corpid, FineClueComboEnum.COMPANY_QUERY.getCode());
        if (fineClueCompanyEntity != null && fineClueCompanyEntity.getExtraExpiry() > DateTimeUtil.getInt()) {
            // 是否为试用
            boolean trialFlag = fineClueCompanyEntity.getExtraExpiry() - fineClueCompanyEntity.getAddTime() < 4 * RedisTimeConstant.LONG_DURATION;
            Integer totalValue = fineClueCompanyEntity.getUseCount();
            Integer usedValue = 1;
            Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
            String usedValueStr = "";
            String memo = trialFlag ? FineCluePackageEnum.BUSINESS_TRIAL.getMemo() : FineCluePackageEnum.BUSINESS.getMemo();
            String warningMemo = "";

            ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.BUSINESS_SEARCH,
                    totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
            return formData;
        }
        return null;
    }

    /**
     * e签宝
     * @param corpid
     * @return com.xbongbong.pro.packageInfo.pojo.ValueAddedInfoPojo
     * @author chy
     * @date 2019-08-15
     */
    private ValueAddedInfoPojo getEsignNumInfo(String corpid) throws XbbException{

        PaasAppEntity paasApp = paasAppModel.getByAlias(SystemAppMenuEnum.ESIGN.getAlias(), corpid);

        if(Objects.nonNull(paasApp) && Objects.equals(paasApp.getEnable(), BasicConstant.ONE)){

            EsignContractMarginVO esignContractMarginVO = esignService.getEsignContractMargin(corpid);

            Integer totalValue = esignContractMarginVO.getCount();
            Integer usedValue = 1;
            Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
            String usedValueStr = "";
            String memo = totalValue + I18nMessageUtil.getMessage(CommonConstant.EACH);
            String warningMemo = "";

            ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.ESIGN,
                    totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
            return formData;
        }
        return null;
    }

    /**
     * 智能报表
     * @param corpid
     * @return
     * @throws XbbException
     */
    private ValueAddedInfoPojo getCustomChartNumInfo(String corpid) throws XbbException {

        //{"totalValue":2, "usedValue":1, "status":1}
        JSONObject totalFormData = getValueAddInfo(corpid, ValueAddedTypeEnum.CUSTOM_CHART_NUM, null, null);
        Integer totalValue = totalFormData.getInteger("totalValue");
        Integer usedValue = totalFormData.getInteger("usedValue");
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
        String usedValueStr = usedValue + I18nMessageUtil.getMessage(CommonConstant.EACH);;
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.USED_TOTAL_CHART);
        memo = String.format(memo, usedValue, totalValue);
        String warningMemo = "";

        ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.CUSTOM_CHART_NUM,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return formData;
    }

    /**
     * 呼叫中心
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getCallCenterInfo(String corpid) {
        Integer totalValue = 1;
        Integer usedValue = 1;
        String userValueStr = "";
        if (Objects.equals(usedValue, 1)) {
            userValueStr = OperateTypeEnum.ENABLE.getName();
        } else {
            userValueStr = OperateTypeEnum.CLOSE.getName();
        }
        Float percentage = 100F;
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.SUPPORT);
        String warningMemo = "";
        ValueAddedInfoPojo callCenter = new ValueAddedInfoPojo(ValueTypeEnum.CALL_CENTER,
                totalValue, usedValue, userValueStr, percentage, memo, warningMemo);
        return callCenter;
    }

    /**
     * api
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getApiInfo(String corpid) throws XbbException  {
        JSONObject numJson = getValueAddInfo(corpid, ValueAddedTypeEnum.API, null, null);
        Integer totalValue = numJson.getInteger("totalValue");
        Integer usedValue = numJson.getInteger("usedValue");
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
        String usedValueStr = "";
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.CONTACT_CUSTOMER_OPEN);
        if (totalValue > 0) {
            memo = OperateTypeEnum.ENABLE.getName();
        }
        String warningMemo = "";
        ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.API,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return formData;
    }

    /**
     * api
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getWorkOrderV2(String corpid) throws XbbException  {
        JSONObject numJson = getValueAddInfo(corpid, ValueAddedTypeEnum.WORK_ORDER_V2, null, null);
        Integer totalValue = numJson.getInteger("totalValue");
        Integer usedValue = numJson.getInteger("usedValue");
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
        String usedValueStr = "";
        Boolean pastDue;
        try {
            pastDue = feeLogModel.workOrderV2PastDue(corpid);
        } catch (XbbException e) {
            pastDue = false;
        }
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.CONTACT_CUSTOMER_OPEN);
        if (!pastDue) {
            memo = OperateTypeEnum.ENABLE.getName();
        }
        String warningMemo = "";
        ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.WORK_ORDER_V2,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return formData;
    }


    /**
     * 业务规则
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getBusinessRulesInfo(String corpid) throws XbbException  {
        //{"totalValue":2, "usedValue":1, "status":1}
        JSONObject totalFormData = getValueAddInfo(corpid, ValueAddedTypeEnum.BUSINESS_RULES, null, null);
        Integer totalValue = totalFormData.getInteger("totalValue");
        Integer usedValue = totalFormData.getInteger("usedValue");
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
        String usedValueStr = "";
        String memo = totalValue + I18nMessageUtil.getMessage(CommonConstant.SET);
        String warningMemo = "";

        ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.BUSINESS_RULES,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return formData;
    }

    /**
     * 批量导入导出
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getImportAndExportInfo(String corpid) {
        Integer totalValue = 1;
        Integer usedValue = 1;
        String userValueStr = "";
        if (Objects.equals(usedValue, 1)) {
            userValueStr = OperateTypeEnum.ENABLE.getName();
        } else {
            userValueStr = OperateTypeEnum.CLOSE.getName();
        }
        Float percentage = 100F;
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.UNLIMITED_USE);
        String warningMemo = "";
        ValueAddedInfoPojo importAndExport = new ValueAddedInfoPojo(ValueTypeEnum.IMPORT_AND_EXPORT,
                totalValue, usedValue, userValueStr, percentage, memo, warningMemo);
        return importAndExport;
    }

    /**
     * 自定义打印
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getCustomPrintInfo(String corpid) {
        Integer totalValue = 1;
        Integer usedValue = 1;
        String userValueStr = "";
        if (Objects.equals(usedValue, 1)) {
            userValueStr = OperateTypeEnum.ENABLE.getName();
        } else {
            userValueStr = OperateTypeEnum.CLOSE.getName();
        }
        Float percentage = 100F;
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.UNLIMITED_TEMPLATE_NUM);
        String warningMemo = "";
        ValueAddedInfoPojo customPrint = new ValueAddedInfoPojo(ValueTypeEnum.CUSTOM_PRINT,
                totalValue, usedValue, userValueStr, percentage, memo, warningMemo);
        return customPrint;
    }

    /**
     * 应用数量 表单数量 报表数量
     * @param corpid
     * @param valueAddedTypeEnum 增值业务类型,用于从缓存取总量和使用量
     * @param valueTypeEnum 套餐业务类型(用于个人中心需要展示的项)
     * @return
     */
    private ValueAddedInfoPojo getSimpleInfo(String corpid, ValueAddedTypeEnum valueAddedTypeEnum,
                                                       ValueTypeEnum valueTypeEnum) throws XbbException {
        JSONObject numJson = getValueAddInfo(corpid, valueAddedTypeEnum, null, null);
        Integer totalValue = numJson.getInteger("totalValue");
        Integer usedValue = numJson.getInteger("usedValue");
        String userValueStr = usedValue + "";
        Float percentage = 0F;
        String memo = "";
        String warningMemo = "";
        if (totalValue > 5000) {
            memo = I18nMessageUtil.getMessage(I18nStringConstant.UNLIMITED);
        } else {
            memo = totalValue + I18nMessageUtil.getMessage(CommonConstant.EACH);
        }
        ValueAddedInfoPojo valueAddedInfoPojo = new ValueAddedInfoPojo(valueTypeEnum,
                totalValue, usedValue, userValueStr, percentage, memo, warningMemo);
        return valueAddedInfoPojo;
    }




    /**
     * 系统容量列表
     * @param corpid 公司id
     * @return
     * 创建时间 2019/4/17 1:56 PM
     * 修改时间 2019/4/17 1:56 PM
     * @author chy
     * @since v1.0
     * @version v1.0
     */
    private List<ValueAddedInfoPojo> getSystemCapacityList(String corpid) throws XbbException {
        List<ValueAddedInfoPojo> systemCapacityList = new ArrayList<>();

        ValueAddedInfoPojo userNum = getUserNumInfo(corpid);
        ValueAddedInfoPojo formData = getFormDataInfo(corpid);
        ValueAddedInfoPojo capacityNum = getCapacityNumInfo(corpid);
        ValueAddedInfoPojo sms = getSmsInfo(corpid);
        ValueAddedInfoPojo customChartNum = getCustomChartNumInfo(corpid);
        systemCapacityList.add(userNum);
        systemCapacityList.add(formData);
        systemCapacityList.add(capacityNum);
        systemCapacityList.add(sms);
        systemCapacityList.add(customChartNum);
        return systemCapacityList;
    }

    /**
     * 短信数
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getSmsInfo(String corpid) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del", 0);
        param.put("corpid", corpid);
        param.put("start", 0);
        param.put("pageNum", 1);

        SmsConfigEntity configEntity = null;
        List<SmsConfigEntity> smsConfigList = smsConfigModel.findEntitys(param);
        if (!smsConfigList.isEmpty()) {
            configEntity = smsConfigList.get(0);
        }

        Integer usedValue = 0;
        Integer totalValue = 0;
        String usedValueStr = "0" + I18nMessageUtil.getMessage(CommonConstant.ARTICLE);
        Float percentage = 0F;
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.USED_TOTAL_ARTICLE);

        if (configEntity != null) {
            Integer smsCount = configEntity.getSmsCount() == null ? 0 : configEntity.getSmsCount();
            Integer sentCount = configEntity.getSentCount() == null ? 0 : configEntity.getSentCount();
            usedValueStr = sentCount + I18nMessageUtil.getMessage(CommonConstant.ARTICLE);
            totalValue = smsCount + sentCount;
            usedValue = sentCount;
            if (totalValue != null && totalValue != 0) {
                percentage = usedValue.floatValue()/totalValue.floatValue() * 100;
            }

        }

        memo = String.format(memo, usedValue, totalValue);

        String warningMemo = "";

        ValueAddedInfoPojo sms = new ValueAddedInfoPojo(ValueTypeEnum.SMS,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return sms;
    }

    /**
     * 文件存储量
     * @param corpid
     * @return
     * @throws XbbException
     */
    private ValueAddedInfoPojo getCapacityNumInfo(String corpid) throws XbbException {
        JSONObject capacityNumJson = getValueAddInfo(corpid, ValueAddedTypeEnum.CAPACITY_NUM, null, null);
        Integer totalValue = capacityNumJson.getInteger("totalValue");
        Integer usedValue = capacityNumJson.getInteger("usedValue");
        String usedValueStr = "";
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;

        Integer usedValueGB = usedValue/1024;
        Integer totalValueGB = totalValue/1024;
        usedValueStr = usedValueGB + "GB";
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.USED_TOTAL_GB );
        memo = String.format(memo, usedValueGB, totalValueGB);
        String warningMemo = "";

        ValueAddedInfoPojo capacityNum = new ValueAddedInfoPojo(ValueTypeEnum.CAPACITY_NUM,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return capacityNum;
    }

    /**
     * 数据量
     * @param corpid
     * @return
     * @throws XbbException
     */
    private ValueAddedInfoPojo getFormDataInfo(String corpid) throws XbbException {

        //{"totalValue":2, "usedValue":1, "status":1}
        JSONObject totalFormData = getValueAddInfo(corpid, ValueAddedTypeEnum.TOTAL_FORM_DATA_NUM, null, null);
        Integer totalValue = totalFormData.getInteger("totalValue");
        Integer usedValue = totalFormData.getInteger("usedValue");
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
        String memo = I18nMessageUtil.getMessage(I18nStringConstant.USED_TOTAL);
        String totalValueStr = MoneyUtil.formatAmount(totalValue.doubleValue(), 0,  I18nMessageUtil.getMessage(CommonConstant.ARTICLE));
        String usedValueStr = MoneyUtil.formatAmount(usedValue.doubleValue(), 0,  I18nMessageUtil.getMessage(CommonConstant.ARTICLE));
        memo = String.format(memo, usedValueStr, totalValueStr);
        String warningMemo = "";

        JSONObject oneFormData = getValueAddInfo(corpid, ValueAddedTypeEnum.ONE_FORM_DATA_NUM, null, null);
        Integer oneStatus = oneFormData.getInteger("status");
        //超标
        if (Objects.equals(oneStatus, PackageStatusEnum.OVER.getCode())) {
            warningMemo = I18nMessageUtil.getMessage(I18nStringConstant.SINGLE_TABLE_EXCEEDS_USAGE_LIMIT);
            Integer oneTotalValue = oneFormData.getInteger("totalValue");
            String oneTotalValueStr = MoneyUtil.formatAmount(oneTotalValue.doubleValue(), 0,  I18nMessageUtil.getMessage(CommonConstant.ARTICLE));
            warningMemo = String.format(warningMemo, oneTotalValueStr);
        }

        ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.FORM_DATA_NUM,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return formData;
    }

    /**
     * 套餐人数
     * @param corpid 公司id
     * @return
     */
    private ValueAddedInfoPojo getUserNumInfo(String corpid) {
        CompanyEntity company = companyModel.getByKey(corpid);
        Integer totalValue = company.getFeeUserNum() == null ? 0 : company.getFeeUserNum();

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);

        Integer usedValue = userModel.getEntitysCount(param);
        String usedValueStr = usedValue + I18nMessageUtil.getMessage(CommonConstant.PEOPLE);
        Float percentage = 0F;

        String memo = String.format(I18nMessageUtil.getMessage(I18nStringConstant.USED), usedValue);

        if (totalValue > 5000){
            percentage = 0F;
            memo += I18nMessageUtil.getMessage(I18nStringConstant.UNLIMITED);
        } else {
            if (!Objects.equals(totalValue, 0)) {
                percentage = usedValue.floatValue()/totalValue.floatValue()*100;
            }
            memo += totalValue + I18nMessageUtil.getMessage(CommonConstant.PEOPLE);
        }
        String warningMemo = "";
        ValueAddedInfoPojo userNum = new ValueAddedInfoPojo(ValueTypeEnum.USER_NUM, totalValue,
                usedValue, usedValueStr, percentage, memo, warningMemo);
        return userNum;
    }

    /**
     * 获取指定增值业务使用及限制值
     * @param corpid
     * @param valueAddedTypeEnum
     * @param xbbRefTypeEnum 获取指定saas业务的单表数据量时，需要传 参照 {@link com.xbongbong.pro.enums.SaasTableCountTypeEnum}
     * @param formId 获取自定义表单的单表数据量时，需要传
     * @return {"totalValue":2, "usedValue":1, "status":1}
     * @throws XbbException
     * 创建时间 2019/4/17 10:34 AM
     * 修改时间 2019/4/17 10:34 AM
     * @author chy
     * @since v1.0
     * @version v1.0
     */
    @Override
    public JSONObject getValueAddInfo(String corpid, ValueAddedTypeEnum valueAddedTypeEnum, XbbRefTypeEnum xbbRefTypeEnum, Long formId) throws XbbException {
        return updatePackageRedisService.getValueAddInfo(corpid, valueAddedTypeEnum, xbbRefTypeEnum, formId);
    }

    @Override
    public void saveApiValueAdd(String corpid, Long startTime, Long endTime) throws XbbException {
        List<FeeEntity> fees = feeModel.getByType(ValueAddedTypeEnum.API.getType());
        if (Objects.isNull(fees) || fees.isEmpty()) {
            //没有套餐，不做处理
            return;
        }
        FeeEntity fee = fees.get(0);
        Long now = DateTimeUtil.getInt();
        FeeLogEntity feeLog = new FeeLogEntity();
        feeLog.setCorpid(corpid);
        feeLog.setCorpName("");
        feeLog.setFeeType(ValueAddedTypeEnum.API.getType());
        feeLog.setFeeId(fee.getId());
        feeLog.setFeeName(fee.getName());
        feeLog.setSumValue(1);
        feeLog.setRealPrice(0F);
        feeLog.setBuyNum(1);
        feeLog.setStartTime(startTime);
        feeLog.setEndTime(endTime);
        feeLog.setMonthNum(null);
        feeLog.setContent("API接口免费试用");
        feeLog.setFee(0F);
        feeLog.setIsPay(1);
        feeLog.setIsInvoice(0);
        feeLog.setPayType(0);
        feeLog.setOpUserName("");
        feeLog.setOrderId("");
        feeLog.setMemo("");
        feeLog.setPayTime(now);
        feeLog.setAddTime(now);
        feeLog.setUpdateTime(now);
        feeLog.setDel(0);
        feeLogModel.insert(feeLog);
    }

    /**
     * api
     * @param corpid
     * @return
     */
    private ValueAddedInfoPojo getDistributorInfo(String corpid) throws XbbException  {
        JSONObject numJson = getValueAddInfo(corpid, ValueAddedTypeEnum.DISTRIBUTOR, null, null);
        Integer totalValue = numJson.getInteger("totalValue");
        Integer usedValue = numJson.getInteger("usedValue");
        Float percentage = usedValue.floatValue()/totalValue.floatValue()*100;
        String usedValueStr = "";
        String memo = totalValue + I18nMessageUtil.getMessage(CommonConstant.SET);
        String warningMemo = "";
        ValueAddedInfoPojo formData = new ValueAddedInfoPojo(ValueTypeEnum.DISTRIBUTOR,
                totalValue, usedValue, usedValueStr, percentage, memo, warningMemo);
        return formData;
    }

    /**
     * 工作流公司套餐界面隐藏业务规则信息
     * @param corpid
     * @return
     */
    private boolean isPackageShowBusinessRule(String corpid) {
        return !commonHelp.isOpenWorkFlow(corpid);
    }
}
